package com.zhixue.order.service.impl;

import com.alibaba.fastjson.*;
import com.alipay.api.*;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhixue.exception.ZhixuePlusException;
import com.zhixue.message.model.po.MqMessage;
import com.zhixue.message.service.MqMessageService;
import com.zhixue.order.config.*;
import com.zhixue.order.mapper.*;
import com.zhixue.order.model.dto.*;
import com.zhixue.order.model.po.*;
import com.zhixue.order.service.XcOrdersService;
import com.zhixue.utils.*;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Auther: 李 力
 * @Date: 2025/5/15
 * @Description: com.zhixue.order.service.impl
 * @version: 1.0
 */
@Service
public class XcOrdersServiceImpl extends ServiceImpl<XcOrdersMapper, XcOrders> implements XcOrdersService {

    @Autowired
    XcOrdersMapper ordersMapper;
    @Autowired
    XcOrdersGoodsMapper ordersGoodsMapper;
    @Autowired
    XcPayRecordMapper payRecordMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private XcOrdersService xcOrdersService;
    @Value("${pay.qrcodeurl}")
    private String payUrl;
    @Value("${pay.alipay.APP_ID}")
    String APP_ID;
    @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY;
    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY;
    @Autowired
    private MqMessageService mqMessageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto) {
        try {
            if (StringUtil.isEmpty(userId) || addOrderDto == null) {
                throw new ZhixuePlusException("参数为空");
            }
            //保存订单
            XcOrders xcOrders = saveXcOrders(userId, addOrderDto);
            //保存支付记录
            XcPayRecord payRecord = createPayRecord(xcOrders);
            //生成二维码
            Long payNo = payRecord.getPayNo();
            payUrl = String.format(payUrl, payNo);
            String qrCode = QRCodeUtil.createQRCode(payUrl, 200, 200);
            PayRecordDto dto = new PayRecordDto();
            BeanUtils.copyProperties(payRecord, dto);
            dto.setQrcode(qrCode);
            return dto;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //根据业务id查询订单
    public XcOrders getOrderByBusinessId(String businessId) {
        XcOrders orders = ordersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId));
        return orders;
    }

    //保存订单
    public XcOrders saveXcOrders(String userId, AddOrderDto addOrderDto) {
        //幂等性判断
        XcOrders order = getOrderByBusinessId(addOrderDto.getOutBusinessId());
        if (order != null) {
            return order;
        }
        order = new XcOrders();
        //生成订单号
        long orderId = IdWorkerUtils.getInstance().nextId();
        order.setId(orderId);
        order.setTotalPrice(addOrderDto.getTotalPrice());
        order.setCreateDate(new Date());
        order.setStatus("600001");//未支付
        order.setUserId(userId);
        order.setOrderType(addOrderDto.getOrderType());
        order.setOrderName(addOrderDto.getOrderName());
        order.setOrderDetail(addOrderDto.getOrderDetail());
        order.setOrderDescrip(addOrderDto.getOrderDescrip());
        order.setOutBusinessId(addOrderDto.getOutBusinessId());//选课记录id
        int insert = ordersMapper.insert(order);
        if (insert <= 0) {
            throw new ZhixuePlusException("插入订单失败");
        }
        Long orderId1 = order.getId();
        String orderDetailJson = addOrderDto.getOrderDetail();
        List<XcOrdersGoods> xcOrdersGoodsList = JSON.parseArray(orderDetailJson, XcOrdersGoods.class);
        for (XcOrdersGoods good : xcOrdersGoodsList) {
            good.setOrderId(orderId1);
            ordersGoodsMapper.insert(good);
        }
        return order;
    }

    //保存支付记录
    public XcPayRecord createPayRecord(XcOrders orders) {
        Long id = orders.getId();
        XcOrders order = ordersMapper.selectById(id);
        if (order == null) {
            throw new ZhixuePlusException("订单不存在");
        }
        if (order.getStatus().equals("601002")) {
            throw new ZhixuePlusException("订单已支付");
        }
        XcPayRecord payRecord = new XcPayRecord();
        //生成支付交易流水号
        long payNo = IdWorkerUtils.getInstance().nextId();
        payRecord.setPayNo(payNo);
        payRecord.setOrderId(orders.getId());//商品订单号
        payRecord.setOrderName(orders.getOrderName());
        payRecord.setTotalPrice(orders.getTotalPrice());
        payRecord.setCurrency("CNY");
        payRecord.setCreateDate(new Date());
        payRecord.setStatus("601001");//未支付
        payRecord.setUserId(orders.getUserId());
        int insert = payRecordMapper.insert(payRecord);
        if (insert <= 0) {
            throw new ZhixuePlusException("插入支付记录失败");
        }
        return payRecord;
    }

    @Override
    public XcPayRecord getPayRecordByPayno(String payNo) {
        return payRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo));
    }

    @Override
    public PayRecordDto queryPayResult(String payNo) {
        //调用支付宝的接口查询支付结果
        PayStatusDto payStatusDto = queryPayResultFromAlipay(payNo);
        //拿到支付结果更新支付记录表和订单表的状态
        xcOrdersService.saveAliPayStatus(payStatusDto);
        //返回最新的支付记录信息
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNo);
        PayRecordDto dto = new PayRecordDto();
        BeanUtils.copyProperties(payRecordByPayno, dto);
        return dto;
    }

    //调用支付宝的接口查询支付结果
    public PayStatusDto queryPayResultFromAlipay(String payNo) {
        //========请求支付宝查询支付结果=============
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE); //获得初始化的AlipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", payNo);
        request.setBizContent(bizContent.toString());
        AlipayTradeQueryResponse response = null;
        try {
            response = alipayClient.execute(request);
            if (!response.isSuccess()) {
                throw new ZhixuePlusException("请求支付查询查询失败");
            }
        } catch (AlipayApiException e) {
            throw new ZhixuePlusException("请求支付查询查询失败");
        }
        //获取支付结果
        String resultJson = response.getBody();
        //转map
        Map resultMap = JSON.parseObject(resultJson, Map.class);
        Map alipay_trade_query_response = (Map) resultMap.get("alipay_trade_query_response");
        //支付结果
        String trade_status = (String) alipay_trade_query_response.get("trade_status");
        String total_amount = (String) alipay_trade_query_response.get("total_amount");
        String trade_no = (String) alipay_trade_query_response.get("trade_no");
        //保存支付结果
        PayStatusDto payStatusDto = new PayStatusDto();
        payStatusDto.setOut_trade_no(payNo);
        payStatusDto.setTrade_status(trade_status);
        payStatusDto.setApp_id(APP_ID);
        payStatusDto.setTrade_no(trade_no);
        payStatusDto.setTotal_amount(total_amount);
        return payStatusDto;
    }

    //拿到支付结果更新支付记录表和订单表的状态
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAliPayStatus(PayStatusDto payStatusDto) {
        //支付流水号
        String payNo = payStatusDto.getOut_trade_no();
        XcPayRecord payRecord = getPayRecordByPayno(payNo);
        if (payRecord == null) {
            throw new ZhixuePlusException("支付记录找不到");
        }
        //支付结果
        String trade_status = payStatusDto.getTrade_status();
        if (trade_status.equals("TRADE_SUCCESS")) {
            //支付金额变为分
            Float totalPrice = payRecord.getTotalPrice() * 100;
            Float total_amount = Float.parseFloat(payStatusDto.getTotal_amount()) * 100;
            //校验是否一致
            if (!payStatusDto.getApp_id().equals(APP_ID) || totalPrice.intValue() != total_amount.intValue()) {
                //校验失败
                throw new ZhixuePlusException("校验支付结果失败");
            }
            XcPayRecord payRecord_u = new XcPayRecord();
            payRecord_u.setStatus("601002");//支付成功
            payRecord_u.setOutPayChannel("Alipay");
            payRecord_u.setOutPayNo(payStatusDto.getTrade_no());//支付宝交易号
            payRecord_u.setPaySuccessTime(new Date());//通知时间
            int update1 = payRecordMapper.update(payRecord_u, new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo));
            if (update1 <= 0) {
                throw new ZhixuePlusException("更新支付记录状态失败");
            }
            //关联的订单号
            Long orderId = payRecord.getOrderId();
            XcOrders orders = ordersMapper.selectById(orderId);
            if (orders == null) {
                throw new ZhixuePlusException("根据支付记录找不到订单");
            }
            XcOrders order_u = new XcOrders();
            order_u.setStatus("600002");//支付成功
            int update = ordersMapper.update(order_u, new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getId, orderId));
            if (update <= 0) {
                throw new ZhixuePlusException("更新订单表状态失败");
            }
            //写消息到数据库
            MqMessage mqMessage = mqMessageService.addMessage("payresult_notify", orders.getOutBusinessId(), orders.getOrderType(), null);
            if (mqMessage == null) {
                throw new ZhixuePlusException("消息保存失败");
            }
            xcOrdersService.notifyPayResult(mqMessage);
            //发送消息
        }
    }

    @Override
    public void notifyPayResult(MqMessage message) {
        //1、消息体，转json
        String msg = JSON.toJSONString(message);
        //设置消息持久化
        Message msgObj = MessageBuilder.withBody(msg.getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .build();
        CorrelationData correlationData = new CorrelationData(message.getId().toString());
        correlationData.getFuture().addCallback(result -> {
            if (result.isAck()) {
                //成功到交换机
                //删除消息表的数据
                mqMessageService.completed(message.getId());
            }
        }, ex -> {
            //消息发送失败
        });
        rabbitTemplate.convertAndSend(PayNotifyConfig.PAYNOTIFY_EXCHANGE_FANOUT, "", msgObj, correlationData);
    }
}
